package com.vinobase.model.dao;


import com.googlecode.objectify.Key;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyFactory;
import com.vinobase.controller.management.CountryForm;
import com.vinobase.controller.management.CountryLocalForm;
import com.vinobase.model.bean.Country;
import com.vinobase.model.bean.CountryLocal;
import com.vinobase.model.bean.Culture;
import com.vinobase.model.bean.PersonalCountry;
import com.vinobase.utils.ResourceNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AuthorizationServiceException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Repository;

import java.security.Principal;
import java.util.*;

@Repository
public class CountryDao {

    @Autowired
    private ObjectifyFactory objectifyFactory;

    @Autowired
    private CultureDao cultureDao;


    @PreAuthorize("hasRole('Admin')")
    public void create(CountryLocal country, Long cultureId, Long countryId){
        Objectify ofy = objectifyFactory.begin();
        country.setCulture(new Key<Culture>(Culture.class, cultureId));
        country.setCountry(new Key<Country>(Country.class, countryId));
        ofy.put(country);
    }

    @PreAuthorize("hasRole('Admin')")
    public void create(Country country){
        Objectify ofy = objectifyFactory.begin();
        ofy.put(country);
    }

    @PreAuthorize("hasRole('Admin')")
    public Set<CountryLocalForm> getCountryLocalForms(Long countryId) {
        Set<CountryLocalForm> res = new HashSet<CountryLocalForm>();
        Objectify ofy = objectifyFactory.begin();
        Key<Country> countryKey = new Key<Country>(Country.class,countryId);

        List<CountryLocal> l = ofy.query(CountryLocal.class).filter("country", countryKey).list();
        for(CountryLocal cl : l){
            CountryLocalForm clf = new CountryLocalForm(cl.getName(), ofy.get(Culture.class,cl.getCulture().getId()).getName());
            res.add(clf);
        }
        return res;
    }

    @PreAuthorize("hasRole('Admin')")
    public SortedSet<CountryForm> getList(){
        SortedSet<CountryForm> res = new TreeSet<CountryForm>();
        Objectify ofy = objectifyFactory.begin();
        Culture cult = ofy.query(Culture.class ).filter("name","en").get();
        Key<Culture> cultureKey = new Key<Culture>(Culture.class,cult.getId());
        List<Country> l = ofy.query(Country.class).list();
        for(Country c : l){
            CountryForm cf = new CountryForm();
            cf.setGlobal(true);
            cf.setId(c.getId());
            Key<Country> countryKey = new Key<Country>(Country.class,c.getId());
            CountryLocal lc = ofy.query(CountryLocal.class).filter("country", countryKey).filter("culture", cultureKey).get();
            cf.setName(lc.getName());
            res.add(cf);
        }
        return res;

    }

    public SortedSet<CountryForm> getList(Locale locale){
        SortedSet<CountryForm> res = new TreeSet<CountryForm>();
        Objectify ofy = objectifyFactory.begin();
        List<Country> l = ofy.query(Country.class).list();
        Key<Culture> cultureKey = cultureDao.getCultureKey(locale);
        for(Country c : l){
            CountryForm cf = new CountryForm();
            cf.setGlobal(true);
            cf.setId(c.getId());
            Key<Country> countryKey = new Key<Country>(Country.class,c.getId());
            CountryLocal lc = ofy.query(CountryLocal.class).filter("country", countryKey).filter("culture", cultureKey).get();
            cf.setName(lc.getName());
            res.add(cf);
        }
        return res;

    }

    public SortedSet<CountryForm> getPersonalList(Principal user){
        SortedSet<CountryForm> res = new TreeSet<CountryForm>();
        Objectify ofy = objectifyFactory.begin();
        List<PersonalCountry> l = ofy.query(PersonalCountry.class).filter("userId", user.getName()).list();
        for(PersonalCountry c : l){
            CountryForm cf = new CountryForm();
            cf.setGlobal(false);
            cf.setId(c.getId());
            cf.setName(c.getName());
            res.add(cf);
        }
        return res;

    }

    public Country get(Long countryId){
        Objectify ofy = objectifyFactory.begin();
        Country c = ofy.find(Country.class, countryId);
        if(c == null) {
            throw new ResourceNotFoundException(countryId);
        }
        return c;
    }

    @PreAuthorize("hasRole('Admin')")
    public void delete(Long countryId){
        Objectify ofy = objectifyFactory.begin();
        Key<Country> countryKey = new Key<Country>(Country.class,countryId);

        List<CountryLocal> l = ofy.query(CountryLocal.class).filter("country", countryKey).list();
        for(CountryLocal cl : l){
            ofy.delete(cl);
        }
        ofy.delete(Country.class, countryId);
    }



    public SortedSet<CountryForm> getList(Principal user, Locale locale){

        SortedSet<CountryForm> countries = new TreeSet<CountryForm>();
        countries.addAll(getList(locale));
        countries.addAll(getPersonalList(user));
        return countries;
       }

    public void create(PersonalCountry pc){
        Objectify ofy = objectifyFactory.begin();
        ofy.put(pc);
    }

    public CountryForm get(Long countryId, Principal user){
        Objectify ofy = objectifyFactory.begin();
        PersonalCountry pc = ofy.find(PersonalCountry.class, countryId);
        if(pc.getUserId().equals(user.getName())){
            CountryForm cf = new CountryForm();
            cf.setId(pc.getId());
            cf.setName(pc.getName());
            return cf;
        }
        else
            throw new AuthorizationServiceException("Illegal access to country : "+countryId);
    }



    public void deletePersonal(Long countryId, Principal user) {
        Objectify ofy = objectifyFactory.begin();
        PersonalCountry pc = ofy.find(PersonalCountry.class, countryId);
        if(pc.getUserId().equals(user.getName()))
            ofy.delete(pc);
        else
            throw new AuthorizationServiceException("Illegal access to country : "+countryId);

    }

}

